/** @file msg_queue.h
 * @brief Message Que handling
 * @author    - Robert Zhang <armner@gmail.com>
 *            - 
 * @date 2013-05
 * @version 1.0.0
 * @note
 */
#ifndef _MSG_QUEQUE_H_
#define _MSG_QUEQUE_H_

#include "frgui.h"
#include "message.h"
#include "stdlib.h"
#include "frgui_port.h"


 extern "C" {
    int sendMessage(HWND hWnd, int message,WPARAM wParam,LPARAM lParam);
}

/** @def connect(psignal, receiver)
 * @brief 
 */
#define connect(psignal, receiver) do{(psignal)->addReceiver(receiver);}while(0)
/** @def disconnect(psignal, receiver)
 * @brief 
 */
#define disconnect(psignal, receiver) do{(psignal)->removeReceiver(receiver);}while(0)

 
#define QUE_DEPTH (32)/**< @def QUE_DEPTH */ 
#define QUE_DEPTH_MASK (QUE_DEPTH-1)/**< @def QUE_DEPTH_MASK */

/** @class WindowList msg_queue.h "core/msg_queue.h"
 * @brief Message Que
 */
class WindowList 
{
public:
    WindowList(HWND hWnd=0, WindowList *next=0){this->hWnd=hWnd; this->next=next;}/**< @brief constructor */
    void operator delete(void *t){port_free(t);}/**< @brief operator 'delete' definitions  */    
    void *operator new(unsigned int len){return port_malloc(len);}/**< @brief operator 'new' definitions  */    
    HWND hWnd;//< window handle  
    WindowList *next;
};


/** @class Signal msg_queue.h "core/msg_queue.h"
 * @brief Message Que
 */
class Signal
{
public:
    Signal(){receiver=0;data=0;}/**< @brief constructor */
	~Signal(){WindowList *pWL; for(; receiver; pWL=receiver, receiver =receiver->next,delete pWL ){}}/**< @brief destructor */
    WindowList *receiver;
    
    
    void emitSignal(){WindowList *pWL; for(pWL=receiver; pWL; pWL=pWL->next) {::sendMessage(pWL->hWnd, MSG_SIGNAL, (WPARAM)this, 0);}}/**< @brief emit signal */
    /** @brief add Receiver
     * @param HWND hWnd
     */
    void addReceiver(HWND hWnd){WindowList *pWL; pWL=new WindowList(hWnd, receiver); receiver =pWL;}
    /** @brief remove Receiver
     * @param HWND hWnd
     */
    void removeReceiver(HWND hWnd)
        {
            WindowList *pWL; 
            if(receiver->hWnd ==hWnd) {pWL=receiver; receiver =receiver->next; delete pWL;}
	     for(pWL=receiver; pWL && pWL->next;)
            {
                if(pWL->next->hWnd ==hWnd)
                {
                    WindowList *t;
                    t =pWL->next;
                    pWL->next =pWL->next->next;
                    delete t;
                    break;
                }
		  else {pWL =pWL->next;}
            }
    	}
    void operator delete(void *t){port_free(t);}/**< @brief operator 'delete' definitions  */ 
    void *operator new(unsigned int len){return port_malloc(len);}/**< @brief operator 'new' definitions  */ 

    //int type;
    //HWND sender;
    void *data;
};

/** @brief message data structure */
typedef struct{
    HWND hWnd;
    int iMsg;
    WPARAM wParam;
    LPARAM lParam;
} Msg, *PMsg;


#define ERR_QUEUE_FULL      (-2)/**< @def ERR_QUEUE_FULL */
#define ERR_OK              (0)/**< @def ERR_OK */
#define ERR_QUEUE_VACANT   (-3)/**< @def ERR_QUEUE_VACANT */

/** @class MsgQue msg_queue.h "core/msg_queue.h"
 * @brief Message Que
 */
class MsgQue
{
public:
    MsgQue();/**< @brief constructor */
    int wr;//< write
    int rd;//< read
    Msg msgBuffer[QUE_DEPTH];//< message buffer

    GUI_LOCK_T lock;//< Multithreading mutex protection
    void LOCK();/**< @brief lock */
    void UNLOCK();/**< @brief unlock */
    void CREATE_LOCK();/**< @brief creat a lock */    
   
    int getMessage(PMsg pMsg);/**< @brief get a message form queue */
    int postMessage(HWND hWnd, int iMsg, WPARAM wParam, LPARAM lParam);/**< @brief post a message to queue */
    void operator delete(void *);/**< @brief operator 'delete' definitions  */ 
    void *operator new(unsigned int len);/**< @brief operator 'new' definitions  */ 
};

extern MsgQue *msgQue;
extern int getMessage(PMsg pMsg);/**< @brief get a message form queue */


#endif
